package com.tbynet.jwp.web;

import com.jfinal.aop.Inject;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.StrKit;
import com.tbynet.jwp.framework.core.JwpInterceptor;
import com.tbynet.jwp.service.spi.UserManager;
import com.tbynet.jwp.model.Users;

/**
 * API认证拦截器
 *
 * 核心职责：
 * 1. API接口身份认证
 * 2. API访问频率控制
 * 3. API权限验证
 * 4. API请求日志记录
 *
 * @author 佰亿互联
 * @version 1.0
 * @since 2025-11-04
 */
public class ApiAuthInterceptor extends JwpInterceptor implements Interceptor {

    // ========== 配置常量 ==========

    /** API公开接口 */
    private static final String[] API_PUBLIC_INTERFACES = {
            "/api/public/",
            "/api/auth/login",
            "/api/auth/register"
    };

    /** 拦截器配置 */
    private final InterceptorConfig config = new InterceptorConfig()
            .setPublicInterfaces(API_PUBLIC_INTERFACES)
            .setLoginUrl("/api/auth/login")
            .setErrorPage("/api/error.json")
            .setMaxRequestsPerMinute(1000);

    // ========== 依赖注入 ==========

    /** 用户管理编排层 - 用于用户验证 */
    @Inject
    private UserManager userManager;

    // ========== 拦截器核心方法 ==========

    /**
     * 拦截器主方法
     *
     * @param inv 拦截器调用对象
     */
    @Override
    public void intercept(Invocation inv) {
        long startTime = System.currentTimeMillis();

        try {
            // 记录请求开始日志
            logRequestStart(inv, "ApiAuthInterceptor");

            String actionKey = inv.getActionKey();
            String clientIp = getClientIp(inv);

            // 检查是否为公开接口
            if (isPublicInterface(actionKey, config.getPublicInterfaces())) {
                log.debug("API公开接口跳过认证，ActionKey: {}", actionKey);
                inv.invoke();
                return;
            }

            // 检查访问频率
            if (!checkAccessRate(clientIp, config.getMaxRequestsPerMinute(), 60)) {
                handleRateLimitExceeded(inv);
                return;
            }

            // API身份认证
            Users user = authenticateApiRequest(inv);
            if (user == null) {
                return; // 认证失败已处理
            }

            // API权限验证
            if (!validateApiPermission(user, actionKey)) {
                return; // 权限验证失败已处理
            }

            // 设置用户上下文
            setupApiContext(inv, user);

            // 执行后续拦截器或Action
            inv.invoke();

        } catch (Exception e) {
            handleInterceptorException(inv, e);
        } finally {
            // 记录请求完成日志
            logRequestComplete(inv, "ApiAuthInterceptor", startTime);
        }
    }

    // ========== 私有方法：API认证 ==========

    /**
     * API身份认证
     *
     * @param inv 拦截器调用对象
     * @return 认证成功的用户对象
     */
    private Users authenticateApiRequest(Invocation inv) {
        String token = getApiToken(inv);

        if (StrKit.isBlank(token)) {
            handleUnauthenticatedApi(inv, "缺少访问令牌");
            return null;
        }

        // 使用Manager层验证token
        Users user = userManager.validateAndGetLoginUser(token);
        if (user == null) {
            handleUnauthenticatedApi(inv, "无效的访问令牌");
            return null;
        }

        log.debug("API认证成功，用户ID: {}, ActionKey: {}",
                user.getID(), inv.getActionKey());

        return user;
    }

    /**
     * 获取API访问令牌
     *
     * @param inv 拦截器调用对象
     * @return API访问令牌
     */
    private String getApiToken(Invocation inv) {
        // 从Header获取token
        String token = inv.getController().getHeader("Authorization");
        if (StrKit.notBlank(token) && token.startsWith("Bearer ")) {
            return token.substring(7);
        }

        // 从参数获取token
        return inv.getController().getPara("access_token");
    }

    /**
     * 验证API权限
     *
     * @param user 用户对象
     * @param actionKey 操作键
     * @return 是否具有API权限
     */
    private boolean validateApiPermission(Users user, String actionKey) {
        // TODO: 实现具体的API权限验证逻辑

        log.debug("API权限验证，用户ID: {}, ActionKey: {}", user.getID(), actionKey);
        return true;
    }

    // ========== 私有方法：上下文设置 ==========

    /**
     * 设置API上下文
     *
     * @param inv 拦截器调用对象
     * @param user 用户对象
     */
    private void setupApiContext(Invocation inv, Users user) {
        // 设置用户信息到request attribute
        inv.getController().setAttr("currentUser", user);
        inv.getController().setAttr("currentUserId", user.getID());

        log.debug("API上下文设置完成，用户ID: {}", user.getID());
    }

    // ========== 私有方法：错误处理 ==========

    /**
     * 处理未认证的API请求
     *
     * @param inv 拦截器调用对象
     * @param reason 原因描述
     */
    private void handleUnauthenticatedApi(Invocation inv, String reason) {
        String actionKey = inv.getActionKey();
        String clientIp = getClientIp(inv);

        log.warn("API认证失败，ActionKey: {}, IP: {}, 原因: {}",
                actionKey, clientIp, reason);

        // 返回JSON错误响应
        inv.getController().renderJson("{\"code\":\"UNAUTHORIZED\",\"msg\":\"认证失败: " + reason + "\"}");

        // 记录安全事件
        logSecurityEvent("API_UNAUTHENTICATED", null, actionKey, clientIp, reason);
    }

    /**
     * 处理访问频率超限
     *
     * @param inv 拦截器调用对象
     */
    private void handleRateLimitExceeded(Invocation inv) {
        String actionKey = inv.getActionKey();
        String clientIp = getClientIp(inv);

        log.warn("API访问频率超限，ActionKey: {}, IP: {}", actionKey, clientIp);

        // 返回JSON错误响应
        inv.getController().renderJson("{\"code\":\"RATE_LIMIT_EXCEEDED\",\"msg\":\"访问频率超限，请稍后重试\"}");

        // 记录安全事件
        logSecurityEvent("API_RATE_LIMIT_EXCEEDED", null, actionKey, clientIp,
                "访问频率超限");
    }

    /**
     * 处理拦截器异常
     *
     * @param inv 拦截器调用对象
     * @param e 异常对象
     */
    private void handleInterceptorException(Invocation inv, Exception e) {
        handleSystemException(inv.getController(), inv, e, config.getErrorPage());
    }
}